#!/usr/bin/env python

from optparse import OptionParser
import urllib
import urllib2
import string
import sys
try: import json #python 2.6 included simplejson as json
except ImportError: import simplejson as json

__author__ = "Hector Rovira"

DATASOURCE_URL = "http://molotovdb.systemsbiology.net/google-dsapi-svc/datasources/molotovdb"

def main():
    parser = OptionParser(usage="%prog [ builds | BUILD_NAME ]")
    parser.add_option("-g", "--genes", dest="geneList", help="comma-separated lists of genes to filter on")
    parser.add_option("-m", "--motifs", dest="motifList", help="comma-separated lists of motifs to filter on")
    parser.add_option("-u", "--upstream", dest="upstream", type="int", default=3000, help="distance upstream of TSS to match (default=3000)")
    parser.add_option("-d", "--downstream", dest="downstream", type="int", default=3000, help="distance downstream of TSS to match (default=3000)")
    parser.add_option("-p", "--pvalue", dest="pvalue", type="float", help="matches motifs with p-value less or equal")
    parser.add_option("-o", "--outputFormat", dest="outputFormat", choices=["csv","tsv","json"], default="tsv", help="desired output type (default=tsv)")
    parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="print debug messages")

    (options, args) = parser.parse_args()

    if len(args) == 0:
        print "WARNING: Please specify a gene build:  use 'python query_molotov_db.py builds' to view a list of builds"
        parser.print_help()
        return

    if args[0] == "builds":
        builds()
        return

    build = args[0]
    genes = []
    if (options.geneList): genes = options.geneList.split(",")
    motifs = []
    if (options.motifList): motifs = options.motifList.split(",")
    upstream=options.upstream
    downstream=options.downstream
    pvalue="%10.10f" % options.pvalue


    if options.verbose: print "DEBUG: [" + build + "," + str(len(genes)) + "," + str(len(motifs)) + "," + str(upstream) + "," + str(downstream) + "," + pvalue + "]"

    # TODO : Determine if this is necessary
    if len(genes) == 0 and len(motifs) == 0:
        print "WARNING: Please specify either a gene list or a motif list"
        parser.print_help()
        return

    tqList = []
    append_wheres(tqList, "GENE_SYMBOL", genes)
    append_wheres(tqList, "PWM_NAME", motifs)
    append_distances(tqList, upstream, downstream)

    if not pvalue == None:
        tqList.append("P_VALUE <= " + pvalue)

    if len(tqList) == 0:
        parser.print_help()
        return

    url = build_url(build, tqList, options.outputFormat, options.verbose)
    req = urllib2.Request(url)
    resp = urllib2.urlopen(req)
    output = resp.read()

    if (resp.info().getheader("Content-Type").startswith("application/json")):
        print json.dumps(json.JSONDecoder().decode(output), sort_keys=True, indent=4)
    else:
        print output

def append_wheres(tqList, fld, items):
    if len(items) > 0:
        str = "("
        for i, item in enumerate(items):
            if i > 0: str += " OR "
            str += fld + "= '" + item + "'"
        str += ")"
        tqList.append(str)

def append_distances(tqList, upstream, downstream):
    distanceStr = "("
    distanceStr += "(DISTANCE_UP >= 0 AND DISTANCE_UP <= " + str(upstream) + ")"
    distanceStr += " OR "
    distanceStr += "(DISTANCE_DOWN >= 0 AND DISTANCE_DOWN <= " + str(downstream) + ")"
    distanceStr += ")"
    tqList.append(distanceStr);

def build_url(build, tqList, outputFormat="tsv", verbose=False):
    tq = "SELECT GENE_SYMBOL, GENE_ID, PWM_NAME, M_CHR, M_START, M_END, M_STRAND, M_CHARACTER_PROBABILITY, M_NORMALIZED_SCORE, M_AGGREGATE_SCORE, SEQUENCE, P_VALUE"
    for i, tqItem in enumerate(tqList):
        if i == 0:
            tq += " WHERE "
        else:
            tq += " AND "
        tq += tqItem

    tqx = tqxout(outputFormat)

    url = DATASOURCE_URL + "/" + build + "/query?" + urllib.urlencode({"tq": tq, "tqx": tqx })

    if verbose:
        print "DEBUG: tq=" + tq
        print "DEBUG: tqx=" + tqx
        print "DEBUG: url=" + url

    return url

def tqxout(outputFormat="tsv"):
    if outputFormat == "csv": return "out:csv_plain"
    if outputFormat == "json": return "out:json_array"
    return "out:tsv"

def builds():
    print "INFO: Retrieving builds from: " + DATASOURCE_URL

    request = urllib2.Request(DATASOURCE_URL)
    resp = urllib2.urlopen(request)

    output = resp.read()
    try:
        buildsJSON = json.loads(output)
        for item in buildsJSON["items"]:
            print " -> " + item["name"]
        print ""
    except:
        fsock = open("list_molotov_db_builds.err", 'w')
        sys.stdout = fsock
        print output
        fsock.close()

if __name__ == "__main__":
    main()